﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Timers;
using AsynchRequest;
using KalamburyManager.Kalambury;
using System.ServiceModel;

namespace KalamburyManager
{
    public class KalamburyGameManager
    {
        Kalambury.KalamburyGameClient client = null;
        Kalambury.User user = null;

        public bool EnableGameStatusMonitor = false;
        public bool EnableImageStatusMonitor = false;
        public bool EnableCheckingUsers = false;
        public bool EnableCheckingImage = true;
        private bool EnableCheckingChat = false;
        Guid prevImageGuid = Guid.NewGuid();
        GameStatus prevGameStatus = GameStatus.NoRoom;
        string _lastMsg = String.Empty;

        RequestAsynchWithTimer image;
        RequestAsynchWithTimer status;
        RequestAsynchWithTimer users;
        RequestAsynchWithTimer alive;
        RequestAsynchWithTimer rooms;
        RequestAsynchWithTimer messages;

        //new image
        public delegate void KalamburyManagerNewImageEventHandler(object sender, KalamburyManagerNewImageEventArgs e);
        public event KalamburyManagerNewImageEventHandler NewImage;

        //changeStatus
        public delegate void KalamburyManagerChangeStatusEventHandler(object sender, KalamburyManagerChangeGameStatus e);
        public event KalamburyManagerChangeStatusEventHandler StatusChanged;

        public delegate void KalamburyManagerCheckEventHandler(object sender, KalamburyManagerUsersEventsArgs e);
        public event KalamburyManagerCheckEventHandler UsersCallback;

        public delegate void KalamburyManagerCheckRoomsEventHandler(object sender, KalamburyManagerRoomCallbackEventArgs e);
        public event KalamburyManagerCheckRoomsEventHandler RoomsCallback;

        public delegate void KalamburyManagerMessagesEventHandler(object sender, KalamburyManagerMessageCallbackEventArgs e);
        public event KalamburyManagerMessagesEventHandler MessagesCallback;

        public KalamburyGameManager(Kalambury.KalamburyGameClient client, Kalambury.User user)
        {
            this.client = client;
            this.user = user;
            prevImageGuid = Guid.NewGuid();
            DoYourJob();
        }

        private void DoYourJob()
        {
            image = new RequestAsynchWithTimer(3000, () =>
            {
                if (EnableCheckingImage)
                { 
                var ret = client.IsNewImage(user, prevImageGuid);
                if (ret.Guid != Guid.Empty && ret.ImageInString != null && ret.ImageInString != "" && prevImageGuid != ret.Guid)
                {
                    prevImageGuid = ret.Guid;
                    if (NewImage != null)
                        NewImage(this, new KalamburyManagerNewImageEventArgs(ret.ImageInString));
                }
                }
            });

            status = new RequestAsynchWithTimer(500, () =>
            {
                var res = client.GetStatus(user);
                if (prevGameStatus != res)
                {
                    prevGameStatus = res;
                    if (StatusChanged != null)
                        StatusChanged(this, new KalamburyManagerChangeGameStatus(res));
                }
            });

            users = new RequestAsynchWithTimer(1000, () =>
            {
                if (EnableCheckingUsers)
                {
                    var res = client.GetUserFromMyRoom(user);
                    if (UsersCallback != null)
                        UsersCallback(this, new KalamburyManagerUsersEventsArgs(res));
                }
            });

            messages = new RequestAsynchWithTimer(1000, () =>
            {
                if (EnableCheckingChat)
                {
                    var res = client.GetMessages(user);
                    if (res != _lastMsg)
                        if (MessagesCallback != null)
                            MessagesCallback(this, new KalamburyManagerMessageCallbackEventArgs(res));
                }
            });
            messages.Start();

            alive = new RequestAsynchWithTimer(1000 * 6, () =>
            {
                client.Ialive(user);
            });
            alive.Start();

            rooms = new RequestAsynchWithTimer(1000 * 2, BeginGetRoom());
            rooms.Start();
        }

        public void Start()
        {
            image.Start();
            status.Start();         
        }

        public void CheckImage(bool check)
        {
            this.EnableCheckingImage = check;
        }

        public void CheckChat(bool check)
        {
            this.EnableCheckingChat = check;
        }

        public void GetRooms()
        {
            new OneRequest(BeginGetRoom());
        }

        private Action BeginGetRoom()
        {
            Action a = () =>
                {
                    var res = client.GetRoomsNames();
                    if (res != null)
                    {
                        if (RoomsCallback != null)
                            RoomsCallback(this, new KalamburyManagerRoomCallbackEventArgs(res));
                    }
                };
            return a;           
        }

        public JoinResult Join(string room)
        {
            EnableCheckingUsers = true;            
            var res = client.JoinRoom(user, room);
            if (res == JoinResult.OK)
            {
                Start();
                users.Start();
            }

            return res;
        }

        public void LeaveRoom()
        {
            EnableCheckingUsers = false;
            try
            {
                client.QuitRoom(user);
            }
            catch (FaultException) { }
            users.Stop();
        }

        public User GetPainter()
        {
            return client.GetPainter(user);
        }

        public string GetAnswer()
        {
            return client.GetAnswer(user);
        }

        public StartedGameStatus iReady()
        {
            return client.StartGame(user);
        }

        public void ResetRoom()
        {
            client.ResetRoom(user);
        }

        public void PutNewImage(string ImageInStr)
        {
            if (!String.IsNullOrEmpty(ImageInStr))
            {
                try
                {
                    client.NewImage(user, ImageInStr);
                }
                catch (ProtocolException)
                {
                    //try next time
                }
            }
        }

        public bool CreateRoom(string RoomName)
        {
            if (!String.IsNullOrEmpty(RoomName))
                return client.CreateRoom(user, RoomName);
            return false;
        }

        public bool CheckAnswer(string Answer)
        {
            return client.CheckAnswer(user, Answer);
        }

        public List<string> GetRoomsNames()
        {
            return client.GetRoomsNames();
        }

        public List<User> GetUserFromMyRoom()
        {
            return client.GetUserFromMyRoom(user);
        }
    }

    public class KalamburyManagerNewImageEventArgs
    {
        public string ImageInString { get; private set; }
        public KalamburyManagerNewImageEventArgs(string ImageInString)
        {
            this.ImageInString = ImageInString;
        }
    }

    public class KalamburyManagerChangeGameStatus
    {
        public GameStatus Status { get; private set; }

        public KalamburyManagerChangeGameStatus(GameStatus Status)
        {
            this.Status = Status;
        }
    }

    public class KalamburyManagerUsersEventsArgs
    {
        public List<User> Users {get; private set;}

        public KalamburyManagerUsersEventsArgs(List<User> users){
            this.Users = users;
        }
    }

    public class KalamburyManagerRoomCallbackEventArgs
    {
        public List<string> Rooms { get; private set; }

        public KalamburyManagerRoomCallbackEventArgs(List<string> roomNames)
        {
            this.Rooms = roomNames;
        }
    }

    public class KalamburyManagerMessageCallbackEventArgs
    {
        public string Messages { get; private set; }

        public KalamburyManagerMessageCallbackEventArgs(string Messages)
        {
            this.Messages = Messages;
        }
    }
}
